<template>
    <div class="upload-img">
        <div class="loading" v-if="loading">
            <i class="el-icon-loading"></i>
        </div>
        <div class="preview-box el-upload-list--picture-card" v-if="fileURl">
            <img :src="$utils.urlFormat(fileURl)" alt="" class="img" />
            <span class="el-upload-list__item-actions">
                <span class="el-upload-list__item-preview" @click="onClickPreview"><i class="el-icon-zoom-in"></i></span>
                <span class="el-upload-list__item-delete" @click="onClickDelete"><i class="el-icon-delete"></i></span>
            </span>
        </div>
        <el-upload
            v-show="!fileURl && !loading"
            ref="elUpload"
            list-type="picture"
            :multiple="false"
            class="upload-demo"
            drag
            :http-request="httpRequest"
            :limit="1"
            :auto-upload="true"
            :show-file-list="false"
            :on-success="onSuccess"
            :on-error="onError"
            :action="action"
            :before-upload="beforeUpload"
        >
            <i class="el-icon-upload"></i>
            <div class="el-upload__text">将图片拖到此处，或<em>点击上传</em></div>
            <template #tip>
                <div class="el-upload__tip">只能上传jpg/png文件，且不超过{{ limit }}M ({{ tip }})</div>
            </template>
        </el-upload>
    </div>
</template>

<script lang="ts">
import { defineComponent, getCurrentInstance, ref, watch } from 'vue';

export default defineComponent({
    name: 'UploadImg',
    props: {
        modelValue: {
            type: String,
            default: ''
        },
        folder: {
            type: String,
            default: 'default'
        },
        tip: {
            type: String,
            default: '建议尺寸为375*232px'
        },
        limit: {
            type: Number,
            default: 1
        },
        width: {
            type: Number,
            default: 1
        },
        height: {
            type: Number,
            default: 0
        }
    },
    emits: ['update:modelValue', 'on-error', 'on-success'],
    setup(props, ctx) {
        const instance: any = getCurrentInstance();
        const GL = instance.appContext.config.globalProperties;
        const loading = ref(false);
        const fileURl = ref('');
        const elUpload: any = ref(null);
        const action = GL.$api.uploadImg;
        watch(
            () => props.modelValue,
            (val) => {
                fileURl.value = val;
            },
            { immediate: true }
        );
        const beforeUpload = (file: any) => {
            const isFormat = file.type.includes('image');
            const isLtxM = file.size / 1024 / 1024 < props.limit;
            if (!isFormat) {
                GL.$message.error('上传格式错误!');
                return false;
            }
            if (!isLtxM) {
                GL.$message.error(`上传图片大小不能超过${props.limit}MB!`);
                return false;
            }
            const isSize = new Promise((resolve, reject) => {
                if (props.height && props.width) {
                    const width = props.width; // 限制图片尺寸为654X270
                    const height = props.height;
                    const url: any = window.URL;
                    const img = new Image();
                    img.onload = () => {
                        const valid = (img.width / img.height).toFixed(2) === (width / height).toFixed(2);
                        valid ? resolve(true) : reject(new Error('尺寸不合法'));
                    };
                    img.src = url.createObjectURL(file);
                } else {
                    resolve(true);
                }
            }).then(
                () => {
                    return file;
                },
                () => {
                    GL.$message.error(`图片尺寸限制比例为${props.width} * ${props.height}`);
                    return Promise.reject(new Error('尺寸不合法'));
                }
            );
            if (!isSize) {
                return false;
            }
            return isFormat && isLtxM && isSize;
        };
        const onSuccess = (res: any) => {
            loading.value = false;
            fileURl.value = res.data.url;
            ctx.emit('on-success', fileURl.value);
            ctx.emit('update:modelValue', fileURl.value);
        };
        const onClickPreview = () => {
            GL.$alert(`<img class="img" style="width:100%;height:auto;" src="${GL.$utils.urlFormat(fileURl.value)}" alt="" />`, '图片预览', {
                dangerouslyUseHTMLString: true,
                customClass: 'img-dialog'
            });
        };
        const onClickDelete = () => {
            fileURl.value = '';
            elUpload.value.clearFiles();
            ctx.emit('update:modelValue', fileURl.value);
        };
        const onError = (err: any) => {
            loading.value = false;
            onClickDelete();
            ctx.emit('on-error', err);
        };
        const httpRequest = (upload: any) => {
            loading.value = true;
            const formData = new FormData();
            formData.append('file', upload.file);
            formData.append('folder', props.folder);
            formData.append('domain', '0');
            GL.$axios
                .post(GL.$api.uploadImg, formData)
                .then((res: any) => {
                    onSuccess(res);
                })
                .catch((err: any) => {
                    onError(err);
                });
        };

        return {
            fileURl,
            loading,
            action,
            elUpload,
            beforeUpload,
            onSuccess,
            onError,
            httpRequest,
            onClickPreview,
            onClickDelete
        };
    }
});
</script>

<style lang="scss">
@import 'index.scss';
</style>
